"""Contains various class for dealing items and inventory"""

from pyre.core import actor
from pyre.data import info
from pyre.ui import element

class Item(actor.Actor):
    """Represents a single item in Ruin"""

    def __init__(self, name, item_info):
        actor.Actor.__init__(self, item_info['face'], name)
        self.melee, self.damage = item_info.get('attack', (0, (0, 0)))
        self.evade, self.protect = item_info.get('defense', (0, (0, 0)))
        self.slot = item_info.get('slot')
        self.flags = item_info.get('flags', {})

        if 'ranged' in self.flags:
            bonus, damage = info.parse_melee(self.flags['ranged'])
            self.flags['ranged:bonus'] = bonus
            self.flags['ranged:damage'] = damage


class ItemInfo(info.InfoDB):
    """Parses item info files"""

    def __init__(self, filename):
        info.InfoDB.__init__(self, filename, face=info.parse_tile,
                                             attack=info.parse_melee,
                                             defense=info.parse_melee,
                                             flags=info.parse_flags)

    def create(self, name):
        return Item(name, self[name])


class Inventory(object):
    """Inventory mixin for Actors which can pick up and equip items"""

    def __init__(self):
        self.pack = []
        self.slots = {}

    def pickup(self):
        items = self.world.get_actors_at(self.pos, Item)
        if items:
            if len(items) == 1:
                item = items.pop()
            else:
                item = element.popup_selector(self.term, items, 'Ground')

            if item:
                item.attach(self)
                self.pack.append(item)
                self.append_message('%s <pick> up the %o', self, item)
            else:
                self.append_message('Invalid selection')
        else:
            self.append_message('There is no item to pick up')

    def drop(self):
        item = self.show_pack()
        if item:
            item.detach()
            self.pack.remove(item)
            self.append_message('%s <drop> %o', self, item)
        else:
            self.append_message('Invalid drop selection')

    def show_pack(self, select=None):
        items = self.pack if select is None else filter(select, self.pack)
        return element.popup_selector(self.term, items, 'Inventory')

    def equip(self):
        item = self.show_pack(lambda item: item.slot is not None)
        if not item:
            self.append_message('Invalid equip selection')
        elif item.slot in self.slots:
            item = self.slots[item.slot]
            self.append_message('%s already <have> %o equipped', self, item)
        else:
            self.pack.remove(item)
            self.slots[item.slot] = item
            self.append_message('%s <equip> %o', self, item)
            if 'sings' in item.flags:
                self.append_message('%s <sing> %a', item, item.flags['sings'])

    def unequip(self):
        slot = self.show_slots()
        if slot:
            slot = slot.split(':')[0]
            item = self.slots[slot]
            del self.slots[slot]
            self.pack.append(item)
            self.append_message('%s <unequip> %o', self, item)
        else:
            self.append_message('Invalid equip selection')

    def show_slots(self):
        items = sorted('{}: {}'.format(s, i) for s, i in self.slots.items())
        return element.popup_selector(self.term, items, 'Equipment')

    def has_flag(self, slot, flag):
        try:
            return flag in self.slots[slot].flags
        except KeyError:
            return False
